package com.livestocksolutions.ui;

import java.util.Date;

import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.livestocksolutions.R;
import com.livestocksolutions.intent.BaseActivity;

/* -- Version History --
 *  1.0 : 10 September 2012 - Initial version.
 */

/**
 * A base class to create the layout for a Bovine Object
 * @author Adam Parr
 * @version 1.0
 * 
 * @.modified 19 October 2012
 */
public class ViewCattleArrayAdapter extends BaseArrayAdapter {
	/**
	 * The Number of characters the NLIS id must be in length to be valid.
	 */
	private static final int NLISIDSize = BaseActivity.getActivity().getResources().getInteger(R.integer.bovine_nlisLength);
	/**
	 * The Number of numbers the RFID must be in length to be valid.
	 */
	private static final int NLISRFSize = BaseActivity.getActivity().getResources().getInteger(R.integer.bovine_rfidLength);
	
	/**
	 * Size of the allowable array passed
	 */
	public static final int SIZE = 12;
	/**
	 * Unique ID for each position within the String[position][{@value #ID}] array passed in the Constructor.
	 */
	public static final int ID = 0;
	/**
	 * Visual ID tag position within the String[position][{@value #VISUALID}] array passed
	 * in the Constructor.
	 */
	public static final int VISUALID = 1;
	/**
	 * NLIS RFID ID position within the String[position][{@value #NLISRFID}] array passed in
	 * the Constructor.
	 */
	public static final int NLISRFID = 2;
	/**
	 * Safe Slaughter date position within the String[position][{@value #WITHHOLD}] array
	 * passed in the Constructor.
	 */
	public static final int WITHHOLD = 7;
	/**
	 * NLIS ID position within the String[position][{@value #NLIS}] array passed in the
	 * Constructor.
	 */
	public static final int NLIS = 4;
	/**
	 * The Gender position within the String[position][{@value #GENDER}] array passed in the
	 * Constructor.
	 */
	public static final int GENDER = 5;
	/**
	 * ID of the breed of this Bovine position within the String[position][{@value #BREED}]
	 * array passed in the Constructor.
	 */
	public static final int BREED = 6;
	/**
	 * Date of birth of this Bovine position within the String[position][{@value #DOB}] array
	 * passed in the Constructor.
	 */
	public static final int DOB = 3;
	/**
	 * Status of this Bovine position within the String[position][{@value #ACTIVE}] array
	 * passed in the Constructor.
	 */
	public static final int ACTIVE = 8;
	/**
	 * The Gender of this Bovine position within the String[position][{@value #DAME}] array
	 * passed in the Constructor.
	 */
	public static final int DAME = 9;
	/**
	 * Id this Bovines Sire in position within the String[position][{@value #SIRE}] array
	 * passed in the Constructor.
	 */
	public static final int SIRE = 10;
	/**
	 * Mob id this Bovine is in position within the String[position][{@value #MOB}]
	 * array passed in the Constructor.
	 */
	public static final int MOB = 11;
	/**
	 * Name position within the String[index][{@value #NAME}] array that are set in
	 * {@link #setMobList(String[][])}, {@link #setDameList(String[][])},
	 * {@link #setSireList(String[][])} and {@link #setBreedList(String[][])}.
	 */
	public static final int NAME = 1;
	
	public static final int GENDER_UNKNOWN 	= 0;
	public static final int GENDER_MALE	 	= 1;
	public static final int GENDER_FEMALE		= 2;
	
	/**
	 * The list of mobs that will be selectable.
	 */
	protected String[][] mobs = new String[][]{};
	
	/**
	 * An array containing a list of possible gender types, this is initialised on the first
	 * creation of this Object type
	 */
	private static String[] genderArray;
	
	/**
	 * An array containing a list of possible Breed types, this must be set after creating an Object of this type
	 * but before calling {@link #getView(int, View, ViewGroup)} if this Bovine is a new one.
	 */
	private static String[][] breedArray;
	/**
	 * An array containing a list of possible Dams to this Bovine.
	 */
	private String[][] dameArray;
	/**
	 * An array containing a list of possible Sires to this Bovine.
	 */
	private String[][] sireArray;
	
	/**
	 * Flags to indicate if these values are valid or not.
	 * for {@link #isValid()} to return true, all of these
	 * flags must equal to true.
	 */
	private boolean validDOB = true, validNLIS = true, validRFID = true;
	
	/**
	 * Constructor
	 * @param context The current context.
	 * @param values The Bovine data to represent in the View.
	 */
	public ViewCattleArrayAdapter(BaseActivity context, String[] values) {
		super(context, new String[][]{values});
		if(genderArray==null){
			genderArray = context.getResources().getStringArray(R.array.cattle_gender);
		}
	}
	
	/**
	 * Constructor
	 * @param context The current context.
	 * @param values The Bovines data to represent in the ListView.
	 */
	protected ViewCattleArrayAdapter(BaseActivity context, String[][] values) {
		super(context, values);
		if(genderArray==null){
			genderArray = context.getResources().getStringArray(R.array.cattle_gender);
		}
	}

	@Override
	public View getView(final int position, View convertView, ViewGroup parent) {
		if(textViewResourceId==0){
			setView(R.layout.item_cattle_view);
		}
		View rowView = super.getView(position, convertView, parent);
		if(Long.parseLong(values[position][ID])==-1 || Long.parseLong(values[position][ID])>0 && values[position][DOB]!=null){
			View dame 				= rowView.findViewById(R.id.cattleDame);
			View sire 				= rowView.findViewById(R.id.cattleSire);
			View breed 				= rowView.findViewById(R.id.cattleBreed);
			View gender				= rowView.findViewById(R.id.cattleGender);
			View mobSpinner			= rowView.findViewById(R.id.cattleMOB);
			
			TextView visualID 		= (TextView) rowView.findViewById(R.id.cattleVisualID);
			TextView rfid 			= (TextView) rowView.findViewById(R.id.cattleRFID);
			TextView nlis 			= (TextView) rowView.findViewById(R.id.cattleNLIS);
			TextView dob 			= (TextView) rowView.findViewById(R.id.cattleDOB);
			TextView activeStatus 	= (TextView) rowView.findViewById(R.id.cattleActive);
			TextView slaughterState = (TextView) rowView.findViewById(R.id.cattleSlaughter);
			
			values[position][VISUALID]=values[position][VISUALID]!=null && values[position][VISUALID].length()>0?values[position][VISUALID]	:"";
			if(rfid!=null){
				values[position][NLISRFID]=values[position][NLISRFID]!=null && values[position][NLISRFID].length()>0?values[position][NLISRFID]	:"";
			}
			if(nlis!=null){
				values[position][  NLIS  ]=values[position][  NLIS  ]!=null && values[position][  NLIS  ].length()>0?values[position][  NLIS  ]	:"";
			}
			values[position][  DOB   ]=values[position][  DOB   ]!=null && values[position][  DOB   ].length()>0?values[position][  DOB   ]	:"";
			values[position][WITHHOLD]=values[position][WITHHOLD]!=null && values[position][WITHHOLD].length()>0?values[position][WITHHOLD]	:"";
			values[position][ GENDER ]=values[position][ GENDER ]!=null && values[position][ GENDER ].length()>0?values[position][ GENDER ]	:"";
			values[position][ BREED  ]=values[position][ BREED  ]!=null && values[position][ BREED  ].length()>0?values[position][ BREED  ]	:"0";
			values[position][ ACTIVE ]=values[position][ ACTIVE ]!=null && values[position][ ACTIVE ].length()>0?values[position][ ACTIVE ]	:"true";
			values[position][  DAME  ]=values[position][  DAME  ]!=null && values[position][  DAME  ].length()>0?values[position][  DAME  ]	:"0";
			values[position][  SIRE  ]=values[position][  SIRE  ]!=null && values[position][  SIRE  ].length()>0?values[position][  SIRE  ]	:"0";
			values[position][  MOB   ]=values[position][  MOB   ]!=null && values[position][  MOB   ].length()>0?values[position][  MOB   ]	:"0";
			
			String[] list;
			switch(textViewResourceId){
				case R.layout.item_cattle_new:
					((Spinner) gender).setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
						public void onItemSelected(AdapterView<?> parent, View view, int index, long id) {
							values[position][GENDER]=genderArray[index];
						}
						public void onNothingSelected(AdapterView<?> parent) {}
					});
					
					// Determine the Gender this Bovine is
					for(int x=0; x < genderArray.length; x++){
						if(values[position][GENDER]==null || genderArray[x].toLowerCase().equals(values[position][GENDER].toLowerCase())){
							((Spinner) gender).setSelection(x);
							break;
						}
					}
					
					((Spinner) breed).setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
						public void onItemSelected(AdapterView<?> parent, View view, int index, long id) {
							values[position][BREED]=breedArray[index][ID];
						}
						public void onNothingSelected(AdapterView<?> parent) {}
					});
					
					// Determine the Breed this Bovine is
					list = new String[breedArray.length];
					for(int x=0; x< breedArray.length; x++){
						list[x]=breedArray[x][NAME];
					}
					((Spinner) breed).setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_spinner_dropdown_item, list));
					
					for(int x=0; x < breedArray.length; x++){
						if(values[position][BREED]==null || breedArray[x][ID].toLowerCase().equals(values[position][BREED].toLowerCase())){
							((Spinner) breed).setSelection(x);
							break;
						}
					}
	
					// Determine the Dame of this Bovine
					((Spinner) dame).setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
						public void onItemSelected(AdapterView<?> parent, View view, int index, long id) {
							values[position][DAME]=dameArray[index][ID];
						}
						public void onNothingSelected(AdapterView<?> parent) {}
					});
					
					list = new String[dameArray.length];
					for(int x=0; x< dameArray.length; x++){
						list[x]=dameArray[x][NAME];
					}
					((Spinner) dame).setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_spinner_dropdown_item, list));
					
					for(int x=0; x < dameArray.length; x++){
						if(values[position][DAME]==null || dameArray[x][ID].toLowerCase().equals(values[position][DAME].toLowerCase())){
							((Spinner) dame).setSelection(x);
							break;
						}
					}
	
					((Spinner) sire).setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
						public void onItemSelected(AdapterView<?> parent, View view, int index, long id) {
							values[position][SIRE]=sireArray[index][ID];
						}
						public void onNothingSelected(AdapterView<?> parent) {}
					});
					
					// Determine the Sire of this Bovine
					list = new String[sireArray.length];
					for(int x=0; x< sireArray.length; x++){
						list[x]=sireArray[x][NAME];
					}
					((Spinner) sire).setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_spinner_dropdown_item, list));
					
					for(int x=0; x < sireArray.length; x++){
						if(values[position][SIRE]==null || sireArray[x][ID].toLowerCase().equals(values[position][SIRE].toLowerCase())){
							((Spinner) sire).setSelection(x);
							break;
						}
					}
	
					dob.addTextChangedListener(new TextWatcher() {
						public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
						public void onTextChanged(CharSequence s, int start, int before, int count) {}
	
						public void afterTextChanged(Editable s) {
							Date d = context.parse(s.toString());
							if(d!=null||s.toString().trim().equals("")){
								values[position][DOB]=s.toString().trim().equals("")?"":String.valueOf(d.getTime());
							}
							if(d==null && !values[position][DOB].equals("") || d!=null && new Date().before(d)){
								validDOB=false;
							}else{
								validDOB=true;
							}
						}
					});
					
					break;
				case R.layout.item_cattle_modify:
				case R.layout.item_cattle_view:
					((TextView) gender).setText(values[position][GENDER]);
					
					// Determine the Breed this Bovine is
					for(int x=0; x < breedArray.length; x++){
						if(values[position][BREED]==null || breedArray[x][ID].toLowerCase().equals(values[position][BREED].toLowerCase())){
							((TextView) breed).setText(breedArray[x][NAME]);
							break;
						}
					}
					boolean found = false;
					// Determine the Dame of this Bovine
					for(int x=0; x < dameArray.length; x++){
						if(dameArray[x][ID].equals(values[0][DAME])){
							((Button) dame).setText(dameArray[x][NAME]);
							found=true;
							break;
						}
					}
					if(!found){
						((Button) dame).setText(context.getResources().getString(R.string.cattle_name_none));
					}
					found=false;
					// Determine the Sire of this Bovine
					for(int x=0; x < sireArray.length; x++){
						if(sireArray[x][ID].equals(values[0][SIRE])){
							((Button) sire).setText(sireArray[x][NAME]);
							found=true;
							break;
						}
					}
					if(!found){
						((Button) sire).setText(context.getResources().getString(R.string.cattle_name_none));
					}
					break;
			}
			
			switch(textViewResourceId){
				case R.layout.item_cattle_new:
				case R.layout.item_cattle_modify:
					visualID.addTextChangedListener(new TextWatcher() {
						public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
						public void onTextChanged(CharSequence s, int start, int before, int count) {}
						public void afterTextChanged(Editable s) {
							values[position][VISUALID]=s.toString();
						}
					});
					if(rfid!=null){
						rfid.addTextChangedListener(new TextWatcher() {
							public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
							public void onTextChanged(CharSequence s, int start, int before, int count) {}
							public void afterTextChanged(Editable s) {
								values[position][NLISRFID]=s.toString().trim().toUpperCase();
								if(values[position][NLISRFID].length()!=NLISRFSize){
									//TODO get the size of the allowed NLIS RFID tag.
									validRFID=false;
								}else{
									validRFID=true;
								}
							}
						});
					}
					if(nlis!=null){
						nlis.addTextChangedListener(new TextWatcher() {
							public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
							public void onTextChanged(CharSequence s, int start, int before, int count) {}
							public void afterTextChanged(Editable s) {
								values[position][NLIS]=s.toString().trim().toUpperCase();
								if(values[position][NLIS].length()!=NLISIDSize){
									validNLIS=false;
								}else{
									validNLIS=true;
								}
							}
						});
					}
					list = new String[mobs.length];
					for(int x=0; x< mobs.length; x++){
						list[x]=mobs[x][NAME];
					}
					((Spinner) mobSpinner).setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_spinner_dropdown_item, list));
					
					((Spinner) mobSpinner).setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
						public void onItemSelected(AdapterView<?> parent, View view, int index, long id) {
							values[position][MOB]=mobs[index][ID];
						}
						public void onNothingSelected(AdapterView<?> parent) {}
					});
					
					// Determine the Mob this Bovine is in
					for(int x=0; x < mobs.length; x++){
						if(values[position][MOB].equals("0") || mobs[x][ID].equals(values[position][MOB])){
							((Spinner) mobSpinner).setSelection(x);
							break;
						}
					}
					
					visualID.setText(values[position][VISUALID]);
					if(rfid!=null){
						rfid.setText(values[position][NLISRFID]);
					}
					if(nlis!=null){
						nlis.setText(values[position][NLIS]);
					}
					break;
				case R.layout.item_cattle_view:
					// Determine the Mob this Bovine is in
					for(int x=0; x < mobs.length; x++){
						if(values[0][MOB].equals("0") || mobs[x][ID].equals(values[0][MOB])){
							((TextView) mobSpinner).setText(mobs[x][NAME]);
							break;
						}
					}
					
					visualID.setText(values[position][VISUALID].length()>0?values[position][VISUALID]:context.getResources().getString(R.string.message_noText,context.getResources().getString(R.string.message_noTag)));
					if(rfid!=null){
						rfid.setText(values[position][NLISRFID].length()>0?values[position][NLISRFID]:context.getResources().getString(R.string.message_noText,context.getResources().getString(R.string.message_noTag)));
					}
					if(nlis!=null){
						nlis.setText(values[position][NLIS].length()>0?values[position][NLIS]:context.getResources().getString(R.string.message_noText,context.getResources().getString(R.string.message_noTag)));
					}
					break;
			}
			
			String s = context.format(context.parse(values[position][DOB]));
			if(s.equals("")){
				dob.setHint(context.getResources().getString(R.string.message_notKnown));
			}else{
				dob.setText(s);
			}
			
			activeStatus.setText(context.getResources().getString(R.string.cattle_active,context.getResources().getString(Boolean.parseBoolean(values[position][ACTIVE])?R.string.cattle_active_active:R.string.cattle_active_inactive)));
			// Check if this date is empty, or before today.
			Date slaughterDate = context.parse(values[position][WITHHOLD]);
			slaughterState.setText(slaughterDate==null||slaughterDate.before(new Date())?
					context.getResources().getString(R.string.cattle_slaughter_safe)
				:
					context.getResources().getString(R.string.cattle_slaughter_notsafe,context.format(slaughterDate))
			);
		}
		return rowView;
	}
	
	/**
	 * Set the list of Mobs that this Bovine could belong to.<br>
	 * The structure of this list is expected to be the First Dimension containing each Mob,
	 * the Second Dimension is structured with {@link #ID} and {@link #NAME}, with ID containing
	 * a String representation of the long id of that Mob, and NAME containing the name of the
	 * Mob.
	 * @param mobList The String Array to use as the list of mobs.
	 */
	public void setMobList(String[][] mobList){
		mobs = mobList;
	}
	
	/**
	 * Set the list of possible Dames that this Bovine could be from.<br>
	 * The structure of this list is expected to be the First Dimension containing each Dame,
	 * the Second Dimension is structured with {@link #ID} and {@link #NAME}, with ID containing
	 * a String representation of the long id of that Dame, and NAME containing the name of the
	 * Sire.
	 * @param dameList The String Array to use as the list of possible Dames.
	 */
	public void setDameList(String[][] dameList){
		dameArray = dameList;
	}
	
	/**
	 * Set the list of possible Sires that this Bovine could be from.<br>
	 * The structure of this list is expected to be the First Dimension containing each Sire,
	 * the Second Dimension is structured with {@link #ID} and {@link #NAME}, with ID containing
	 * a String representation of the long id of that Sire, and NAME containing the name of the
	 * Sire.
	 * @param sireList The String Array to use as the list of possible Sires.
	 */
	public void setSireList(String[][] sireList){
		sireArray = sireList;
	}
	
	/**
	 * Set the list of Breeds that this Bovine could be of.<br>
	 * The structure of this list is expected to be the First Dimension containing each Breed,
	 * the Second Dimension is structured with {@link #ID} and {@link #NAME}, with ID containing
	 * a String representation of the long id of that Breed, and NAME containing the name of the
	 * Breed.
	 * @param breedList The String Array to use as the list of possible Breeds.
	 */
	public static void setBreedList(String[][] breedList){
		breedArray = breedList;
	}
	
	/**
	 * Display the View that will allow the modification of all fields.<br>
	 * This should be used when adding a new Bovine (or when Gender is Undefined).
	 */
	public void setNewCattle(){
		setView(R.layout.item_cattle_new);
	}
	
	/**
	 * Display the View that will allow the modification of some fields.<br>
	 * This should be used when choosing to modify the Bovine.
	 */
	public void setModifyCattle(){
		setView(R.layout.item_cattle_modify);
	}
	
	/**
	 * Display the View that will only display the Bovine details.
	 */
	public void setViewCattle(){
		setView(R.layout.item_cattle_view);
	}
	
	@Override
	public boolean isValid(){
		boolean dobNumber = true;
		Date d = null;
		// Update all values to the latest versions
		values[0][VISUALID]	=((TextView) root.findViewById(R.id.cattleVisualID)).getText().toString();
		View v = root.findViewById(R.id.cattleRFID);
		if(v!=null){
			values[0][NLISRFID]	=((TextView)v).getText().toString();
		}
		v = root.findViewById(R.id.cattleNLIS);
		if(v!=null){
			values[0][NLIS]		=((TextView)v).getText().toString();
		}
		switch(textViewResourceId){
			case R.layout.item_cattle_new:
				if(!values[0][DOB].equals("")){
					d = new Date(Long.parseLong(values[0][DOB]));
					if(new Date().before(d)){
						dobNumber = false;
					}
				}

				values[0][GENDER]	=genderArray[((Spinner)root.findViewById(R.id.cattleGender)).getSelectedItemPosition()];
				values[0][BREED]	=breedArray[((Spinner)root.findViewById(R.id.cattleBreed)).getSelectedItemPosition()][ID];
				values[0][DAME]		=dameArray[((Spinner)root.findViewById(R.id.cattleDame)).getSelectedItemPosition()][ID];
				values[0][SIRE]		=sireArray[((Spinner)root.findViewById(R.id.cattleSire)).getSelectedItemPosition()][ID];
				break;
			case R.layout.item_cattle_modify:
				values[0][MOB]		=mobs[((Spinner)root.findViewById(R.id.cattleMOB)).getSelectedItemPosition()][ID];
				break;
		}
		
		// Do Validation
		validDOB=(values[0][DOB].equals("") || dobNumber);
		validNLIS=values[0][NLIS]==null||values[0][NLIS].length()==NLISIDSize || values[0][NLIS].length()==0 || NLISIDSize==0;
		validRFID=values[0][NLIS]==null||values[0][NLISRFID].length()==NLISRFSize || values[0][NLISRFID].length()==0 || NLISRFSize==0;
		
		if(validDOB && validNLIS && validRFID){
			return true; // Valid
		}
		
		// Something(s) are not valid, inform the user.
		String s = "";
		if(!validDOB){
			if(d!=null){
				s=context.getString(R.string.message_invalidDATEAfter,context.getResources().getString(R.string.cattle_dob),DATEFORMATSTRINGSHORT);
			}else{
				s=context.getString(R.string.message_invalidDATE,context.getResources().getString(R.string.cattle_dob),DATEFORMATSTRINGSHORT);
			}
		}
		if(!validNLIS){
			s=s!=""?s+"\n\n":s;
			s+=context.getString(R.string.message_bovine_invalidLength,context.getResources().getString(R.string.cattle_NLIS),NLISIDSize,values[0][NLIS].length());
		}
		if(!validRFID){
			s=s!=""?s+"\n\n":s;
			s+=context.getString(R.string.message_bovine_invalidLength,context.getResources().getString(R.string.cattle_RFID),NLISRFSize,values[0][NLISRFID].length());
		}
		Toast.makeText(context,s, Toast.LENGTH_LONG).show();

		return false;
	}
}